package com.syezon.wifikey.cengwang;

import android.content.Context;
import android.net.DhcpInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.support.annotation.NonNull;
import android.text.TextUtils;

import com.syezon.wifikey.utils.Utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;


/**
 * Created by admin on 2017/4/19.
 */

public class WiFiTerminalUtils {

    private static Map<String, String> terminalMap = new LinkedHashMap<>();

    private static String[] pcArray = new String[]{"dell", "hp", "acer", "founder", "ibm", "sony", "microsoft", "msi", "toshiba", "clevo", "vmware", "azurewave", "intel"};
    private static String[] mobieArray = new String[]{"apple", "oppo", "vivo", "huawei", "xiaomi", "samsung", "htc", "meizu", "gionee", "yulong", "lemobile", "zte", "oneplus"};
    private static String[] interchangerArray = new String[]{"h3c", "cisco", "d-link", "netgear", "tp-link", "mercury", "tenda", "netcore", "fast"};
    private static String[] monitorArray = new String[]{"hikvision", "dahua", "tyco", "yaan"};

    private static List<String> pcList = Arrays.asList(pcArray);
    private static List<String> mobileList = Arrays.asList(mobieArray);
    private static List<String> exchangeList = Arrays.asList(interchangerArray);
    private static List<String> monitorList = Arrays.asList(monitorArray);

    /**
     * 获取IP
     */
    public static String getHostIp() {
        try {
            WifiManager wifiManager = (WifiManager) Utils.getApp().getApplicationContext().getSystemService(Context.WIFI_SERVICE);
            WifiInfo wifiInfo = wifiManager.getConnectionInfo();
            int ip = wifiInfo.getIpAddress();
            return int2ip(ip);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 获取wifi名字
     */
    public static String getWifiName(Context context) {
        try {
            WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
            WifiInfo wifiInfo = wifiManager.getConnectionInfo();
            return wifiInfo.getSSID();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取wifi信号强度
     */
    public static int getWifiRssi(Context context) {
        try {
            WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
            WifiInfo wifiInfo = wifiManager.getConnectionInfo();
            return wifiInfo.getRssi();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return -100;//MIN_RSSI
    }

    /**
     * 获取wifi Mac地址
     */
    public static String getMacAddress(Context context) {
        try {
            WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
            WifiInfo wifiInfo = wifiManager.getConnectionInfo();
            return wifiInfo.getMacAddress();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * @return 获取wifi网关地址
     */
    public static String getGateWay() {
        WifiManager wifiManager = (WifiManager) Utils.getApp().getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        DhcpInfo di = wifiManager.getDhcpInfo();
        int gateWayIp = di.gateway;
        return int2ip(gateWayIp);//网关地址
    }

    /**
     * int值转换为ip地址
     */
    private static String int2ip(int paramInt) {
        return (paramInt & 0xFF) + "." + (0xFF & paramInt >> 8) + "." + (0xFF & paramInt >> 16) + "."
                + (0xFF & paramInt >> 24);
    }

    /**
     * @return wifi的信道
     */
    public static int getCurrentChannel(Context context) {
        try {
            WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
            WifiInfo wifiInfo = wifiManager.getConnectionInfo();// 当前wifi连接信息
            List<ScanResult> scanResults = wifiManager.getScanResults();
            for (ScanResult result : scanResults) {
                if (result.BSSID.equalsIgnoreCase(wifiInfo.getBSSID()) && result.SSID.equalsIgnoreCase(wifiInfo.getSSID().substring(1, wifiInfo.getSSID().length() - 1))) {
                    return getChannelByFrequency(result.frequency);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return -1;
    }

    /**
     * 获取信道评分列表里的list数据
     */
    public static List<GateWayDetail> getGateWayDetailList(Context context) {
        WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        List<ScanResult> scanResultList = wifiManager.getScanResults();
        List<GateWayDetail> gateWayDetailList = new ArrayList<>();
        gateWayDetailList.add(new GateWayDetail(1));
        gateWayDetailList.add(new GateWayDetail(2));
        gateWayDetailList.add(new GateWayDetail(3));
        gateWayDetailList.add(new GateWayDetail(4));
        gateWayDetailList.add(new GateWayDetail(5));
        gateWayDetailList.add(new GateWayDetail(6));
        gateWayDetailList.add(new GateWayDetail(7));
        gateWayDetailList.add(new GateWayDetail(8));
        gateWayDetailList.add(new GateWayDetail(9));
        gateWayDetailList.add(new GateWayDetail(10));
        gateWayDetailList.add(new GateWayDetail(11));
        gateWayDetailList.add(new GateWayDetail(12));
        gateWayDetailList.add(new GateWayDetail(13));

        for (ScanResult scanResult : scanResultList) {
            int channel = getChannelByFrequency(scanResult.frequency);
            switch (channel) {
                case 1:
                    //信道1同频加1，信道2、3、4、5邻频加1
                    List<ScanResult> scanResultList1 = gateWayDetailList.get(0).getSameFrequencyScanResultList();
                    scanResultList1.add(scanResult);

                    for (int i = 1; i < 5; i++) {
                        List<ScanResult> scanResultList_ = gateWayDetailList.get(i).getDifferentFrequencyScanResultList();
                        scanResultList_.add(scanResult);
                    }
                    break;
                case 2:
                    //信道2同频加1，信道1、3、4、5、6邻频加1
                    List<ScanResult> scanResultList2 = gateWayDetailList.get(1).getSameFrequencyScanResultList();
                    scanResultList2.add(scanResult);
                    for (int i = 0; i < 1; i++) {
                        List<ScanResult> scanResultList_ = gateWayDetailList.get(i).getDifferentFrequencyScanResultList();
                        scanResultList_.add(scanResult);
                    }
                    for (int i = 2; i > 1 && i < 6; i++) {
                        List<ScanResult> scanResultList_ = gateWayDetailList.get(i).getDifferentFrequencyScanResultList();
                        scanResultList_.add(scanResult);
                    }
                    break;
                case 3:
                    //信道3同频加1，信道1、2、4、5、6、7邻频加1
                    List<ScanResult> scanResultList3 = gateWayDetailList.get(2).getSameFrequencyScanResultList();
                    scanResultList3.add(scanResult);
                    for (int i = 0; i < 2; i++) {
                        List<ScanResult> scanResultList_ = gateWayDetailList.get(i).getDifferentFrequencyScanResultList();
                        scanResultList_.add(scanResult);
                    }
                    for (int i = 3; i > 2 && i < 7; i++) {
                        List<ScanResult> scanResultList_ = gateWayDetailList.get(i).getDifferentFrequencyScanResultList();
                        scanResultList_.add(scanResult);
                    }
                    break;
                case 4:
                    //信道4同频加1，信道1、2、3、5、6、7、8邻频加1
                    List<ScanResult> scanResultList4 = gateWayDetailList.get(3).getSameFrequencyScanResultList();
                    scanResultList4.add(scanResult);
                    for (int i = 0; i < 3; i++) {
                        List<ScanResult> scanResultList_ = gateWayDetailList.get(i).getDifferentFrequencyScanResultList();
                        scanResultList_.add(scanResult);
                    }
                    for (int i = 4; i > 3 && i < 8; i++) {
                        List<ScanResult> scanResultList_ = gateWayDetailList.get(i).getDifferentFrequencyScanResultList();
                        scanResultList_.add(scanResult);
                    }
                    break;
                case 5:
                    //信道5同频加1，信道1、2、3、4、6、7、8、9邻频加1
                    List<ScanResult> scanResultList5 = gateWayDetailList.get(4).getSameFrequencyScanResultList();
                    scanResultList5.add(scanResult);
                    for (int i = 0; i < 4; i++) {
                        List<ScanResult> scanResultList_ = gateWayDetailList.get(i).getDifferentFrequencyScanResultList();
                        scanResultList_.add(scanResult);
                    }
                    for (int i = 5; i > 4 && i < 9; i++) {
                        List<ScanResult> scanResultList_ = gateWayDetailList.get(i).getDifferentFrequencyScanResultList();
                        scanResultList_.add(scanResult);
                    }
                    break;
                case 6:
                    //信道6同频加1，信道2、3、4、5、7、8、9、10邻频加1
                    List<ScanResult> scanResultList6 = gateWayDetailList.get(5).getSameFrequencyScanResultList();
                    scanResultList6.add(scanResult);
                    for (int i = 1; i < 5; i++) {
                        List<ScanResult> scanResultList_ = gateWayDetailList.get(i).getDifferentFrequencyScanResultList();
                        scanResultList_.add(scanResult);
                    }
                    for (int i = 6; i > 5 && i < 10; i++) {
                        List<ScanResult> scanResultList_ = gateWayDetailList.get(i).getDifferentFrequencyScanResultList();
                        scanResultList_.add(scanResult);
                    }
                    break;
                case 7:
                    //信道7同频加1，信道3、4、5、6、8、9、10、11邻频加1
                    List<ScanResult> scanResultList7 = gateWayDetailList.get(6).getSameFrequencyScanResultList();
                    scanResultList7.add(scanResult);
                    for (int i = 2; i < 6; i++) {
                        List<ScanResult> scanResultList_ = gateWayDetailList.get(i).getDifferentFrequencyScanResultList();
                        scanResultList_.add(scanResult);
                    }
                    for (int i = 7; i > 6 && i < 11; i++) {
                        List<ScanResult> scanResultList_ = gateWayDetailList.get(i).getDifferentFrequencyScanResultList();
                        scanResultList_.add(scanResult);
                    }
                    break;
                case 8:
                    //信道8同频加1，信道4、5、6、7、9、10、11、12邻频加1
                    List<ScanResult> scanResultList8 = gateWayDetailList.get(7).getSameFrequencyScanResultList();
                    scanResultList8.add(scanResult);
                    for (int i = 3; i < 7; i++) {
                        List<ScanResult> scanResultList_ = gateWayDetailList.get(i).getDifferentFrequencyScanResultList();
                        scanResultList_.add(scanResult);
                    }
                    for (int i = 8; i > 7 && i < 12; i++) {
                        List<ScanResult> scanResultList_ = gateWayDetailList.get(i).getDifferentFrequencyScanResultList();
                        scanResultList_.add(scanResult);
                    }
                    break;
                case 9:
                    //信道9同频加1，信道5、6、7、8、10、11、12、13邻频加1
                    List<ScanResult> scanResultList9 = gateWayDetailList.get(8).getSameFrequencyScanResultList();
                    scanResultList9.add(scanResult);
                    for (int i = 4; i < 8; i++) {
                        List<ScanResult> scanResultList_ = gateWayDetailList.get(i).getDifferentFrequencyScanResultList();
                        scanResultList_.add(scanResult);
                    }
                    for (int i = 9; i > 8 && i < 13; i++) {
                        List<ScanResult> scanResultList_ = gateWayDetailList.get(i).getDifferentFrequencyScanResultList();
                        scanResultList_.add(scanResult);
                    }
                    break;
                case 10:
                    //信道10同频加1，信道6、7、8、9、11、12、13邻频加1
                    List<ScanResult> scanResultList10 = gateWayDetailList.get(9).getSameFrequencyScanResultList();
                    scanResultList10.add(scanResult);
                    for (int i = 5; i < 9; i++) {
                        List<ScanResult> scanResultList_ = gateWayDetailList.get(i).getDifferentFrequencyScanResultList();
                        scanResultList_.add(scanResult);
                    }
                    for (int i = 10; i > 9 && i < 13; i++) {
                        List<ScanResult> scanResultList_ = gateWayDetailList.get(i).getDifferentFrequencyScanResultList();
                        scanResultList_.add(scanResult);
                    }
                    break;
                case 11:
                    //信道11同频加1，信道7、8、9、10、12、13邻频加1
                    List<ScanResult> scanResultList11 = gateWayDetailList.get(10).getSameFrequencyScanResultList();
                    scanResultList11.add(scanResult);
                    for (int i = 6; i < 10; i++) {
                        List<ScanResult> scanResultList_ = gateWayDetailList.get(i).getDifferentFrequencyScanResultList();
                        scanResultList_.add(scanResult);
                    }
                    for (int i = 11; i > 10 && i < 13; i++) {
                        List<ScanResult> scanResultList_ = gateWayDetailList.get(i).getDifferentFrequencyScanResultList();
                        scanResultList_.add(scanResult);
                    }
                    break;
                case 12:
                    //信道12同频加1，信道8、9、10、11、13邻频加1
                    List<ScanResult> scanResultList12 = gateWayDetailList.get(11).getSameFrequencyScanResultList();
                    scanResultList12.add(scanResult);
                    for (int i = 7; i < 11; i++) {
                        List<ScanResult> scanResultList_ = gateWayDetailList.get(i).getDifferentFrequencyScanResultList();
                        scanResultList_.add(scanResult);
                    }
                    for (int i = 12; i > 11 && i < 13; i++) {
                        List<ScanResult> scanResultList_ = gateWayDetailList.get(i).getDifferentFrequencyScanResultList();
                        scanResultList_.add(scanResult);
                    }
                    break;
                case 13:
                    //信道13同频加1，信道9、10、11、12邻频加1
                    List<ScanResult> scanResultList13 = gateWayDetailList.get(12).getSameFrequencyScanResultList();
                    scanResultList13.add(scanResult);
                    for (int i = 8; i < 12; i++) {
                        List<ScanResult> scanResultList_ = gateWayDetailList.get(i).getDifferentFrequencyScanResultList();
                        scanResultList_.add(scanResult);
                    }
                    break;
            }
        }
        return gateWayDetailList;
    }

    /**
     * 根据频率获得信道
     */
    public static int getChannelByFrequency(int frequency) {
        int channel = -1;
        switch (frequency) {
            case 2412:
                channel = 1;
                break;
            case 2417:
                channel = 2;
                break;
            case 2422:
                channel = 3;
                break;
            case 2427:
                channel = 4;
                break;
            case 2432:
                channel = 5;
                break;
            case 2437:
                channel = 6;
                break;
            case 2442:
                channel = 7;
                break;
            case 2447:
                channel = 8;
                break;
            case 2452:
                channel = 9;
                break;
            case 2457:
                channel = 10;
                break;
            case 2462:
                channel = 11;
                break;
            case 2467:
                channel = 12;
                break;
            case 2472:
                channel = 13;
                break;
            case 2484:
                channel = 14;
                break;
            case 5745:
                channel = 149;
                break;
            case 5765:
                channel = 153;
                break;
            case 5785:
                channel = 157;
                break;
            case 5805:
                channel = 161;
                break;
            case 5825:
                channel = 165;
                break;
        }
        return channel;
    }

    /**
     * 进行arp请求，刷新arp缓存列表
     */
    private static void arpRequest() {
        try {
            String hostIp = getHostIp();
//            LogUtil.d("arpRequest","hostIp="+hostIp);
            if (!TextUtils.isEmpty(hostIp)) {
                int index = hostIp.lastIndexOf(".");
                String ipPrefix = hostIp.substring(0, index + 1);//"192.168.70."

                for (int i = 0; i < 256; i++) {
                    String ip = ipPrefix + i;
                    try {
                        boolean isReachable = InetAddress.getByName(ip).isReachable(15);
                    } catch (Exception e) {
                    }
//                    LogUtil.d("arpRequest","\n"+"   ip="+ip+"   isReachable="+isReachable);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
//            LogUtil.e("terminal","arpRequestException   "+e.getMessage());
        }
    }

    public static TerminalInfo getSelfTerminalInfo() {
        String connectWifiSsid = getConnectWifiSsid(Utils.getApp());
        TerminalInfo terminalInfo = new TerminalInfo(TerminalInfo.TYPE_MOBILE, getHostIp(), connectWifiSsid + " （当前设备）", getManufacture(getMacAddress(Utils.getApp())));
        return terminalInfo;
    }

    /**
     * 获取连接wifi的名字
     */
    private static String getConnectWifiSsid(Context context) {
        String ssid = "";
        try {
            WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
            WifiInfo info = wifiManager.getConnectionInfo();
            ssid = info.getSSID();
            if (!TextUtils.isEmpty(ssid)) {
                ssid = ssid.replaceAll("\"", "");
            }
        } catch (Exception e) {
        }
        return ssid;
    }

    public static List<TerminalInfo> getTerminalInWifi() {
        arpRequest();
        List<TerminalInfo> terminalList = new ArrayList<>();
        List<String> resultList = readFileLines("/proc/net/arp");
        if (resultList.size() > 1) {
            for (int j = 1; j < resultList.size(); ++j) {
                String r = resultList.get(j);
                String[] splits = r.split(" +");
                if (splits.length > 4) {
                    String ip = splits[0];
                    String mac = splits[3];
                    if (TextUtils.equals(mac, "00:00:00:00:00:00")) {
                        continue;
                    }
                    String manufacture = getManufacture(mac);
                    int type = getManufactureType(mac);
                    TerminalInfo terminalInfo = new TerminalInfo(type, ip, mac, manufacture);
                    terminalList.add(terminalInfo);
                }
            }
        }
        return terminalList;
    }


    private static String getManufacture(String mac) {
        String macSuffix = "";
        if (mac != null && mac.length() >= 8) {
            macSuffix = mac.substring(0, 8);
        }
        String macSuffix2 = macSuffix.replace(":", "");
        if (terminalMap.isEmpty()) {
            initManufacturer();
        }
        String manufacture = "通用设备";
        String manufactureMap = terminalMap.get(macSuffix2.toUpperCase());
        if (!TextUtils.isEmpty(manufactureMap)) {
            manufacture = manufactureMap;
        }
        return manufacture;
    }

    private static int getManufactureType(String mac) {
        int type = TerminalInfo.TYPE_UNKNOWN;
        String macSuffix = "";
        if (mac != null && mac.length() >= 8) {
            macSuffix = mac.substring(0, 8);
        }
        String macSuffix2 = macSuffix.replace(":", "");
        if (terminalMap.isEmpty()) {
            initManufacturer();
        }
        String manufacture = terminalMap.get(macSuffix2.toUpperCase());
        if (!TextUtils.isEmpty(manufacture)) {
            String manufactureLowerCase = manufacture.toLowerCase();
            if (pcList.contains(manufactureLowerCase)) {
                type = TerminalInfo.TYPE_PC;
            } else if (mobileList.contains(manufactureLowerCase)) {
                type = TerminalInfo.TYPE_MOBILE;
            } else if (exchangeList.contains(manufactureLowerCase)) {
                type = TerminalInfo.TYPE_EXCHANGE;
            } else if (monitorList.contains(manufactureLowerCase)) {
                type = TerminalInfo.TYPE_MONITOR;
            } else {
                type = TerminalInfo.TYPE_PC;
            }
        }
        return type;
    }

    private static synchronized void initManufacturer() {
        BufferedReader reader = null;
        try {
            InputStream inputStream = Utils.getApp().getAssets().open("manufacturer.txt");
            reader = new BufferedReader(new InputStreamReader(inputStream));
            String line;
            HashMap initTerminalMap = new HashMap<>(24000);
            while ((line = reader.readLine()) != null) {
                String trim = line.trim();
                if (trim.length() > 6) {
                    String macPrefix = trim.substring(0, 6);
                    String manufacture = trim.substring(7);
                    initTerminalMap.put(macPrefix, manufacture);
                }
            }
            if (terminalMap.isEmpty()) {
                terminalMap.putAll(initTerminalMap);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 以行为单位读取文件，常用于读面向行的格式化文件
     */
    private static List<String> readFileLines(String fileName) {
        File file = new File(fileName);
        BufferedReader reader = null;
        String tempString = "";
        List<String> mResult = new ArrayList<>();
        try {
            reader = new BufferedReader(new FileReader(file));
            while ((tempString = reader.readLine()) != null) {
                mResult.add(tempString);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return mResult;
    }

    public static class TerminalInfo implements Comparable<TerminalInfo> {

        public static final int TYPE_UNKNOWN = 0;
        public static final int TYPE_PC = 1;
        public static final int TYPE_MOBILE = 2;
        public static final int TYPE_EXCHANGE = 3;
        public static final int TYPE_MONITOR = 4;

        private int type;
        private String ip;
        private String mac;
        private String gateWay;
        private String manufacturer;


        public TerminalInfo(int type, String ip, String mac, String manufacturer) {
            this.type = type;
            this.ip = ip;
            this.mac = mac;
            this.manufacturer = manufacturer;
            try {
                gateWay = getGateWay();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        public int getType() {
            return type;
        }

        public void setType(int type) {
            this.type = type;
        }

        public String getIp() {
            return ip;
        }

        public void setIp(String ip) {
            this.ip = ip;
        }

        public String getMac() {
            return mac;
        }

        public void setMac(String mac) {
            this.mac = mac;
        }

        public String getManufacturer() {
            return manufacturer;
        }

        public void setManufacturer(String manufacturer) {
            this.manufacturer = manufacturer;
        }

        @Override
        public String toString() {
            return "TerminalInfo{" +
                    "ip='" + ip + '\'' +
                    ", mac='" + mac + '\'' +
                    '}';
        }

        @Override
        public int compareTo(@NonNull TerminalInfo another) {
            int differ = 0;
            if (TextUtils.equals(ip, gateWay)) {
                return -1;
            }
            if (TextUtils.equals(another.ip, gateWay)) {
                return 1;
            }
            try {
                int i = ip.lastIndexOf(".");
                int j = another.ip.lastIndexOf(".");
                int self = Integer.parseInt(ip.substring(i + 1));
                int other = Integer.parseInt(another.ip.substring(j + 1));
                differ = self - other;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return differ;
        }
    }

    public static class GateWayDetail {
        private int channel;
        private List<ScanResult> sameFrequencyScanResultList;
        private List<ScanResult> differentFrequencyScanResultList;

        public GateWayDetail(int channel) {
            this.channel = channel;
            sameFrequencyScanResultList = new ArrayList<>();
            differentFrequencyScanResultList = new ArrayList<>();
        }

        public int getChannel() {
            return channel;
        }

        public void setChannel(int channel) {
            this.channel = channel;
        }

        public List<ScanResult> getSameFrequencyScanResultList() {
            return sameFrequencyScanResultList;
        }

        public void setSameFrequencyScanResultList(List<ScanResult> sameFrequencyScanResultList) {
            this.sameFrequencyScanResultList = sameFrequencyScanResultList;
        }

        public List<ScanResult> getDifferentFrequencyScanResultList() {
            return differentFrequencyScanResultList;
        }

        public void setDifferentFrequencyScanResultList(List<ScanResult> differentFrequencyScanResultList) {
            this.differentFrequencyScanResultList = differentFrequencyScanResultList;
        }
    }
}
